package 每日一题;

import java.util.Arrays;
import java.util.Collections;

/**
 * 1105. 填充书架
 * 给定一个数组 books ，其中 books[i] = [thicknessi, heighti] 表示第 i 本书的厚度和高度。你也会得到一个整数 shelfWidth 。
 * <p>
 * 按顺序 将这些书摆放到总宽度为 shelfWidth 的书架上。
 * <p>
 * 先选几本书放在书架上（它们的厚度之和小于等于书架的宽度 shelfWidth ），然后再建一层书架。重复这个过程，直到把所有的书都放在书架上。
 * <p>
 * 需要注意的是，在上述过程的每个步骤中，摆放书的顺序与你整理好的顺序相同。
 * <p>
 * 例如，如果这里有 5 本书，那么可能的一种摆放情况是：第一和第二本书放在第一层书架上，第三本书放在第二层书架上，第四和第五本书放在最后一层书架上。
 * 每一层所摆放的书的最大高度就是这一层书架的层高，书架整体的高度为各层高之和。
 * <p>
 * 以这种方式布置书架，返回书架整体可能的最小高度。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * <p>
 * <p>
 * 输入：books = [[1,1],[2,3],[2,3],[1,1],[1,1],[1,1],[1,2]], shelfWidth = 4
 * 输出：6
 * 解释：
 * 3 层书架的高度和为 1 + 3 + 2 = 6 。
 * 第 2 本书不必放在第一层书架上。
 * 示例 2:
 * <p>
 * 输入: books = [[1,3],[2,4],[3,2]], shelfWidth = 6
 * 输出: 4
 * <p>
 * <p>
 * 提示：
 * <p>
 * 1 <= books.length <= 1000
 * 1 <= thicknessi <= shelfWidth <= 1000
 * 1 <= heighti <= 1000
 */
public class D230423_T1105 {

    int[][] BOOKS;
    int SHELFW;
    int[] dp;

    public int minHeightShelves(int[][] books, int shelfWidth) {
        BOOKS = books;
        SHELFW = shelfWidth;
        dp = new int[books.length];
        Arrays.fill(dp, -1);
        return dfs(books.length - 1);
    }

    /**
     * 第i 本书 放入书架 的最低高度
     *
     * @param index 第几本书 坐标从0开始
     * @return 书架最低高度
     */
    public int dfs(int index) {

        if (index < 0) {
            return 0;
        }
        if (dp[index] != -1) {
            return dp[index];
        }
        //最后 i到k 本书 放在一层 或不在一层 k= 最后1到K本书的厚度相加小于等于书架宽度
        int res = Integer.MAX_VALUE;
        int leftW = SHELFW;//本层剩余宽度
        int maxH = 0; //本层高度
        for (int j = index; j >= 0; --j) {
            leftW -= BOOKS[j][0];
            if (leftW < 0) break; // 空间不足，无法放书
            maxH = Math.max(maxH, BOOKS[j][1]); // 从 j 到 i 的最大高度
            res = Math.min(res, dfs(j - 1) + maxH);
        }
        dp[index] = res;
        return dp[index] = res; // 记忆化

    }

}
